package com.qiwenshare.common.util;

import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.net.util.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class JjwtUtil {
 
	// jti：jwt的唯一身份标识
	public static final String JWT_ID = UUID.randomUUID().toString();
 
	// 加密密文，私钥
	public static final String JWT_SECRET = "jiamimiwen";
 
	// 过期时间，单位毫秒
	public static final int EXPIRE_TIME = 60 * 60 * 1000; // 一个小时
//	public static final long EXPIRE_TIME = 7 * 24 * 3600 * 1000; // 一个星期
 
	// 由字符串生成加密key
	public static SecretKey generalKey() {
		String secret = JWT_SECRET;
		// 本地的密码解码
		byte[] encodedKey = Base64.decodeBase64(JWT_SECRET);
		// 根据给定的字节数组使用AES加密算法构造一个密钥
		SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
		return key;
	}
 
	// 创建jwt
	public static String createJWT(String issuer, String audience, String subject) throws Exception {
		// 设置头部信息
//		Map<String, Object> header = new HashMap<String, Object>();
//		header.put("typ", "JWT");
//		header.put("alg", "HS256");
		// 或
		// 指定header那部分签名的时候使用的签名算法，jjwt已经将这部分内容封装好了，只有{"alg":"HS256"}
		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
		// 创建payload的私有声明（根据特定的业务需要添加，如果要拿这个做验证，一般是需要和jwt的接收方提前沟通好验证的方式）
		Map<String, Object> claims = new HashMap<>();
		claims.put("username", "admin");
		claims.put("password", "010203");
		// jti用户id，例如：20da39f8-b74e-4a9b-9a0f-a39f1f73fe64
		String jwtId = JWT_ID;
		// 生成JWT的时间
		long nowTime = System.currentTimeMillis();
		Date issuedAt = new Date(nowTime);
		// 生成签名的时候使用的秘钥secret，切记这个秘钥不能外露，是你服务端的私钥，在任何场景都不应该流露出去，一旦客户端得知这个secret，那就意味着客户端是可以自我签发jwt的
		SecretKey key = generalKey();
		// 为payload添加各种标准声明和私有声明
		JwtBuilder builder = Jwts.builder() // 表示new一个JwtBuilder，设置jwt的body
//				.setHeader(header) // 设置头部信息
				.setClaims(claims) // 如果有私有声明，一定要先设置自己创建的这个私有声明，这是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了那些标准的声明
				.setId(jwtId) // jti(JWT ID)：jwt的唯一身份标识，根据业务需要，可以设置为一个不重复的值，主要用来作为一次性token，从而回避重放攻击
				.setIssuedAt(issuedAt) // iat(issuedAt)：jwt的签发时间
				.setIssuer(issuer) // iss(issuer)：jwt签发者
				.setSubject(subject) // sub(subject)：jwt所面向的用户，放登录的用户名，一个json格式的字符串，可存放userid，roldid之类，作为用户的唯一标志
				.signWith(signatureAlgorithm, key); // 设置签名，使用的是签名算法和签名使用的秘钥
		// 设置过期时间
		long expTime = EXPIRE_TIME;
		if (expTime >= 0) {
			long exp = nowTime + expTime;
			builder.setExpiration(new Date(exp));
		}
		// 设置jwt接收者
		if (audience == null || "".equals(audience)) {
			builder.setAudience("Tom");
		} else {
			builder.setAudience(audience);
		}
		return builder.compact();
	}
 
	// 解密jwt
	public static Claims parseJWT(String jwt) throws Exception {
		SecretKey key = generalKey(); // 签名秘钥，和生成的签名的秘钥一模一样
		Claims claims = Jwts.parser() // 得到DefaultJwtParser
				.setSigningKey(key) // 设置签名的秘钥
				.parseClaimsJws(jwt).getBody(); // 设置需要解析的jwt
		return claims;
	}
	
	public static void main(String[] args) {
		Claims claims = null;
		try {
			claims = parseJWT("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ7XCJhZGRyQXJlYVwiOlwi6ZuB5aGU5Yy6XCIsXCJhZGRyQ2l0eVwiOlwi6KW_5a6J5biCXCIsXCJhZGRyUHJvdmluY2VcIjpcIumZleilv-ecgVwiLFwiYmVnaW5Db3VudFwiOjAsXCJiaXJ0aGRheVwiOlwiMTk5NC0wNS0wNlwiLFwiY3VycmVudFBhZ2VcIjowLFwiZWRpdG9yVHlwZVwiOjAsXCJlbWFpbFwiOlwiMTE2MjcxNDQ4M0BxcS5jb21cIixcImVzc2F5Q291bnRcIjowLFwiaW1hZ2VVcmxcIjpcIi91cGxvYWQvMjAyMDA3MTUvODA5NjE1OTQ4MjEzODkwNTkuanBnXCIsXCJpbmR1c3RyeVwiOlwi6K6h566X5py66KGM5LiaXCIsXCJpbnRyb1wiOlwi6ZSZ5oqK6ZmI6YaL5b2T5oiQ5aKo77yM5YaZ5bC95Y2K55Sf6YO95piv6YW444CCXCIsXCJsYXN0TG9naW5UaW1lXCI6XCIyMDIwLTEwLTI3IDE5OjAxOjU0XCIsXCJub3RSZWFkQ291bnRcIjowLFwicGFnZUNvdW50XCI6MCxcInBhc3N3b3JkXCI6XCI3NjcyYmE0NDc4OTY5NTlmNmU1NDQ1NTcxOGY2ZWU2ZlwiLFwic2FsdFwiOlwiMzY5MjQ1NzgxMDIyMDg3NlwiLFwic2V4XCI6XCLnlLdcIixcInRlbGVwaG9uZVwiOlwiMTg4MjkyOTE4MTdcIixcInVzZXJJZFwiOjIsXCJ1c2VybmFtZVwiOlwiTUFDXCJ9IiwiYXVkIjoicWl3ZW4iLCJwYXNzd29yZCI6IjAxMDIwMyIsImlzcyI6InFpd2Vuc2hhcmUiLCJleHAiOjE2MDM4MDA0MDcsImlhdCI6MTYwMzc5NjgwNywianRpIjoiNzYzZTE0NDMtYmZjYS00MDkzLTg3NGYtMzlmMzQ1ODRiZDkyIiwidXNlcm5hbWUiOiJhZG1pbiJ9.Gv_QlXZEiT_-mbI2Iz6oa2SqgBXwVzsS_xK8RhvF7oY");
		} catch (Exception e) {
			e.printStackTrace();
		}
		String subject = claims.getSubject();
		System.out.println(subject);
	}


 
}